home *** CD-ROM | disk | FTP | other *** search
- /*
- * Yamana's Otomeza Plug-in Tool
- * MAGセーバ
- *
- * 1995.07.17
- * 1995.07.26 2倍程度の高速化
- * 1995.08.06 メモリの浪費を抑えるためバッファのページ化を行った
- * 1995.08.09 乙女座V1.3b 仕様に変更
- * 1995.08.13 ページ化を強化しメモリ不足に対処
- *
- * バグ
- * ・フラグBのサイズが大きくなる。なんで??
- *
- * "MAG" (c) Woddy-RINN
- */
-
- #include "otome_pi.h"
-
- const char longname[] = "FILE : まぐせーば";
- const char extend[] = "MAG";
-
- #define USE_FILE PI_SAVE
- #include "otome_pi.c"
-
- /* 01234567012340123456789012345678 */
- char MAG_check[] = "MAKI02 TOWN >謎< ";
- char def_comment[]= "MAGSAVER/OTOMEZA";
-
- #define POS_USER 13
- #define LEN_USER 18
- #define LEN_TOPDATA (8+4+1+LEN_USER+1)
-
- typedef struct
- {
- char head;
- char machine;
- char machine_dat;
- char screen;
- short sx;
- short sy;
- short ex;
- short ey;
- long flgA;
- long flgB;
- long flgB_size;
- long pixel;
- long pixel_size;
- }MagHeader;
-
- char *user='\0',*comment='\0';
-
- extern char *my_getenv();
-
- #define MAX_PIXPAGESIZE (32*1024)
- int pixPageSize= MAX_PIXPAGESIZE;
- int pixPage = 0;
-
- int flgBPageSize= MAX_PIXPAGESIZE;
- int flgBPage = 0;
-
- char *mem,*flg[2],*flgA,**flgB,**pixel;
-
- /**********************************************************************/
- /*** 圧縮用メモリ確保 ***/
-
- int MAG_mallocBuffers( vramWidth,Height )
- int vramWidth,Height;
- {
- extern void freePixBuf();
-
- if( (mem=PI_MALLOC(
- (vramWidth+8)*2 /* 作業用フラグバッファ */
- +(vramWidth*Height+7)/8+8 /* フラグA */
- ))==NULL )
- {
- return PI_ERROR_NO_MEMORY;
- }
- if( mallocPixBuf( vramWidth,Height ) )
- { PI_FREE( mem );
- return PI_ERROR_NO_MEMORY;
- }
- if( mallocFlgBBuf( vramWidth,Height ) )
- { freePixBuf();
- PI_FREE( mem );
- return PI_ERROR_NO_MEMORY;
- }
-
- /* メモリ割り当て */
- flg[0]= mem ;
- flg[1]= mem + (vramWidth+8) ;
- flgA = mem + (vramWidth+8)*2 ;
-
- return NOERR;
- }
-
- void MAG_freeBuffers()
- {
- extern void freePixBuf();
-
- PI_FREE( mem );
- freePixBuf();
-
- }
-
- /****** MAG フォーマット圧縮部 ******/
-
- int MAG_encode( head,buf )
- MagHeader *head;
- char *buf;
- {
- char Bit[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
-
- /* フラグのチェック順序で圧縮効率が左右される */
- #if 0
- char flgOrder[] = { 0,1,4,5,6,7,9,10,2,8,11,12,13,14,3,15 };
- char flgTable[][2] =
- { { 0, 0},
- { 2, 0},{ 0, 1},{ 2, 1},{ 0, 2},{ 2, 2}, /* 1, 4, 5, 6, 7 */
- { 0, 4},{ 2, 4},{ 4, 0},{ 4, 2},{ 4, 4}, /* 9,10, 2, 8,11 */
- { 0, 8},{ 2, 8},{ 4, 8},{ 8, 0},{ 0,16} /* 12,13,14, 3,15 */
- };
- #else /* こっちは yamana-a オリジナルの順番 */
- char flgOrder[] = { 0,1,4,2,6,5,7,9,8,10,11,12,13,14,3,15 };
- char flgTable[][2] =
- { { 0, 0},
- { 2, 0},{ 0, 1},{ 4, 0},{ 0, 2},{ 2, 1}, /* 1, 4, 5, 6, 7 */
- { 2, 2},{ 0, 4},{ 4, 2},{ 2, 4},{ 4, 4}, /* 9,10, 2, 8,11 */
- { 0, 8},{ 2, 8},{ 4, 8},{ 8, 0},{ 0,16} /* 12,13,14, 3,15 */
- };
- #endif
-
- int Width,Height, flgWidth, vramWidth, realWidth;
- int i,j;
- register int x,y,x1,y1;
- int p0,p1, upper;
- int flgAi,flgBi,pixi;
-
- realWidth = (head->ex - head->sx +1 );
- Height = (head->ey - head->sy +1 );
-
- /***
- 16色
- 2ドット=1バイト
- 4ドット=2バイト=1ピクセル
- 8ドット=4バイト=2ピクセル=1フラグ
-
- 256色
- 1ドット=1バイト
- 2ドット=2バイト=1ピクセル
- 4ドット=4バイト=2ピクセル=1フラグ
- ***/
-
- /* バッファには32ドット単位で格納されているので注意 */
- if( head->screen == 0 )
- { vramWidth =((realWidth+31)& 0xffe0)>>1 ;
- Width =((realWidth+ 7)& 0xfff8)>>1 ; /* 8ドット単位で記録 */
- head->ex = (head->sx + (Width<<1) - 1);
- }else
- { vramWidth = (realWidth+31)& 0xffe0 ;
- Width = (realWidth+ 7)& 0xfff8 ; /* ほんとは4ドット単位だが */
- head->ex = (head->sx + Width - 1); /* この際だから統一させる */
- }
- flgWidth = Width>>2 ; /* フラグ単位のときの幅 */
-
- if( MAG_mallocBuffers( vramWidth,Height ) )
- return ERROR;
-
- /******** フラグデータ作成 ********/
-
- pixi = flgAi = flgBi = 0;
- flgA[0] = 0;
- for( y=0; y<Height ; y++ )
- {
- for( x=0; x<Width; x+=2 )
- flg[y & 1][ x>>2 ] = 0; /* 1フラグ=2ピクセル=4バイト*/
-
- for( x=0; x<Width; x+=2 ) /* 2バイト単位 */
- {
- #if 0
- if( x+4 >= Width ) /* 右端の4バイトについては */
- { j = (x+2)-realWidth/2; /* 黒の塗りつぶしチェック */
- if( j > 1 )
- p0 = 0, /* ゴミが出ないよう埋める */
- WORD( buf + x + y*vramWidth ) = 0;
- else if( j==1 )
- p0 = BYTE( buf + x + y*vramWidth ),
- WORD( buf + x + y*vramWidth ) &= 0x00ff ;
- else
- p0 = WORD( buf + x + y*vramWidth );
- }else
- #endif
- p0 = WORD( buf + x + y*vramWidth );
-
- for( i=1; i<16; i++ ) /* 同じピクセルを探す */
- {
- x1= (x - flgTable[i][0]);
- y1= (y - flgTable[i][1]);
- if( x1<0 || y1<0 ) continue;
-
- p1 = WORD( buf + x1 + y1*vramWidth );
-
- /* 近くに同じピクセルがある? */
- if( p0 == p1 )
- { flg[ y&1 ][ x>>2 ]
- |= ( (int)flgOrder[i] << (((x & 2)==0)? 4:0 ));
- break;
- }
- }
- if( i==16 ) /* 見つからないときは、その点を記録 */
- {
- if( pixi >= pixPageSize ) /* ページ切替え */
- { if( remallocPixBuf() )
- return PI_ERROR_NO_MEMORY;
- pixi = 0;
- }
- if( head->screen ) /* 256色 */
- { pixel[pixPage][ pixi++ ] = ( p0 & 0xff);
- pixel[pixPage][ pixi++ ] = ((p0>>8) & 0xff);
- }else
- { /* 上位下位入替え */
- p1 = (( p0 & 0xf0f0 )>>4 );
- p0 = (( p0 & 0x0f0f )<<4 );
- p0 |= p1 ;
-
- pixel[pixPage][ pixi++ ] = (char)( p0 );
- pixel[pixPage][ pixi++ ] = (char)((p0>>8));
-
- }
- }
- }/* x<Width */
-
- /* ここまでで1ラインぶんのフラグ作成完了 */
- /* 続いてフラグA、Bを作成する */
-
- for ( x=0; x< flgWidth; x++ )
- {
- if( y>0 ) /* 上のラインとXORをとる */
- upper = (flg[y & 1][x] ^ flg[(y-1) & 1][x] );
- else
- upper = (flg[y & 1][x] );
-
- if( upper != 0 )
- { /* flgA は 8ビット単位なので、ビットカウンタflgAiの */
- /* 下位3ビットは無視する */
- flgA[ flgAi>>3] |= Bit[ flgAi & 7 ] ;
-
- if( flgBi >= flgBPageSize ) /* ページ切替え */
- { if( remallocFlgBBuf() )
- return PI_ERROR_NO_MEMORY;
- flgBi = 0;
- }
- flgB[flgBPage][ flgBi++ ] = upper ;
- }
- if( (flgAi & 7)== 7 ) /* 次のフラグを初期化 */
- flgA[ (flgAi>>3)+1 ] = 0 ;
-
- flgAi++;
-
- }
- }/* y<Height */
-
- flgAi = (flgAi+7)/8 ; /* flgAi はビットカウンタ */
- if( flgAi & 1 ) flgAi++;
- if( flgBi & 1 ) flgBi++;
-
-
- /** ヘッダの書換えを行う **/
-
- head->flgA = (sizeof(MagHeader)+(head->screen==0 ? 16*3:256*3));
- head->flgB = (head->flgA + flgAi);
- head->flgB_size = (flgBPage*flgBPageSize + flgBi);
- head->pixel = (head->flgB + head->flgB_size);
- head->pixel_size= (pixPage*pixPageSize + pixi);
-
- return NOERR;
- }
-
- /*********************************************/
- /* ピクセルデータのページ管理
- **
- ** MAG エンコードのとき圧縮後のデータを格納するため、最悪の場合 vram と
- ** 同じ大きさのピクセル用メモリが必要となる。
- ** ただし、最悪の場合を想定していては無駄なメモリを増加させるだけなので
- ** ページ単位でメモリを確保し、足りなくなったら追加確保するようにする。
- **
- */
-
- void freePixBuf()
- {
- int i;
-
- for( i=0; i<=pixPage; i++ )
- PI_FREE( pixel[i] );
- PI_FREE( pixel );
- }
-
- int mallocPixBuf( Width,Height )
- int Width,Height;
- {
- int all,page;
-
- all = Width * Height ; /* 全画面データに必要なメモリ */
- page = (all / pixPageSize )+1 ; /* 最大ページサイズ */
-
- if( (pixel=(char**)PI_MALLOC( sizeof(char*)*page ))==NULL )
- return ERROR;
-
- /* 1ページだけ確保 */
- if( (pixel[0] = (char*)PI_MALLOC( pixPageSize + 2 ))==NULL )
- { free( pixel );
- return ERROR;
- }
-
- return NOERR;
- }
-
- int remallocPixBuf()
- {
- if( (pixel[pixPage+1] = (char*)PI_MALLOC( pixPageSize + 2 ))==NULL )
- { freePixBuf();
- return ERROR;
- }
- pixPage++;
- return NOERR;
- }
-
- /** flgB バッファのメモリ対策 **/
-
- void freeFlgBBuf()
- {
- int i;
-
- for( i=0; i<=flgBPage; i++ )
- PI_FREE( flgB[i] );
- PI_FREE( flgB );
- }
-
- int mallocFlgBBuf( Width,Height )
- int Width,Height;
- {
- int all,page;
-
- all = Width * Height ; /* 全画面データに必要なメモリ */
- page = (all / flgBPageSize )+1 ; /* 最大ページサイズ */
-
- if( (flgB=(char**)PI_MALLOC( sizeof(char*)*page ))==NULL )
- return ERROR;
-
- /* 1ページだけ確保 */
- if( (flgB[0] = (char*)PI_MALLOC( flgBPageSize + 2 ))==NULL )
- { free( flgB );
- return ERROR;
- }
-
- return NOERR;
- }
-
- int remallocFlgBBuf()
- {
- if( (flgB[flgBPage+1] = (char*)PI_MALLOC( flgBPageSize + 2 ))==NULL )
- { freeFlgBBuf();
- return ERROR;
- }
- flgBPage++;
- return NOERR;
- }
-
- /**********************************************************************/
-
- int MAG_head( head,palette,fr,pal )
- char *palette;
- MagHeader *head;
- FRAME *fr;
- char *pal;
- {
- int i,j,col;
- char *p;
-
- /** ファイル識別部分 **/
-
- p = '\0';
- if( user != '\0' ) p = user;
- else p = my_getenv("USER");
-
- if( p != '\0' )
- { for( i=0; i<LEN_USER && p[i]!='\0' ; i++ ) /* ユーザ名 */
- MAG_check[ POS_USER+i ] = p[i];
- for( ; i<LEN_USER ; i++ )
- MAG_check[ POS_USER+i ] = ' ';
- }
-
- /** ヘッダ **/
-
- head->head = 0x00;
- head->machine = 0x00;
- head->machine_dat= 0x00;
- head->sx = fr->lupx;
- head->sy = fr->lupy;
- head->ex = fr->rdwx; /* ←圧縮の際に必要なのでまだ変更しない! */
- head->ey = fr->rdwy;
-
- if( (col = DWORD(pal))!=16 && col!=256 )
- return ERROR;
-
- if( col<256 ) head->screen = 0x00;
- else head->screen = 0x80;
-
- /*** パレットデータ ***/
-
- for( i=0,j=8; i<col; i++,j+=8 )
- {
- palette[ i*3 ] = pal[ j+2 ] ; /* G */
- palette[ i*3+1 ] = pal[ j+1 ] ; /* R */
- palette[ i*3+2 ] = pal[ j ] ; /* B */
- }
-
- return NOERR;
- }
-
- int MAG_writeBuffers( fp,head,palette )
- FILE *fp;
- MagHeader *head;
- char *palette;
- {
- int i;
- char *p;
-
- /****/
-
- i = strlen( MAG_check );
- if( i != fwrite( MAG_check, 1, i, fp) )
- return ERROR;
-
- if( comment == '\0' ) p = def_comment;
- else p = comment;
- fwrite( p, 1, strlen(p), fp);
- fputc( '\x1a' , fp);
-
- /****/
-
- fwrite( head, sizeof(MagHeader), 1, fp);
- fwrite( palette, 1, (head->screen ==0 ? 16*3:256*3) ,fp);
-
- /****/ /* ここまで慎重にならなくてよいかも */
-
- i = (head->flgB - head->flgA);
- if( i != fwrite( flgA, 1, i, fp) )
- return ERROR;
-
- for( i=0; i<flgBPage; i++ )
- if( flgBPageSize != fwrite( &flgB[i][0], 1, flgBPageSize, fp ) )
- return ERROR;
- if( (i = head->flgB_size % flgBPageSize) >0 )
- if( i != fwrite( &flgB[flgBPage][0], 1, i, fp ) )
- return ERROR;
-
- for( i=0; i<pixPage; i++ )
- if( pixPageSize != fwrite( &pixel[i][0], 1, pixPageSize, fp ) )
- return ERROR;
- if( (i = head->pixel_size % pixPageSize) >0 )
- if( i != fwrite( &pixel[pixPage][0], 1, i, fp ) )
- return ERROR;
-
- return NOERR;
- }
-
- int MAG_save( fp, buf,fr,pix,pal )
- char *buf,*pal;
- FILE *fp;
- int pix;
- FRAME *fr;
- {
- int ret;
- int col;
-
- MagHeader head;
- char *palette;
-
- col = ((pix==8) ? 256 : 16);
-
- /* パレット用メモリ確保 */
- if( (palette = PI_MALLOC( 3*col ))==NULL )
- return PI_ERROR_NO_MEMORY;
-
- /*** ヘッダ作成 ***/
- if( MAG_head( &head, palette,fr,pal ) )
- { free(palette);
- return ERROR ;
- }
- /*** 圧縮 ***/
-
- ret = MAG_encode( &head, buf );
- if( ret!=NOERR )
- goto savequit;
-
- /*** 書き出し ***/
-
- ret = MAG_writeBuffers( fp, &head, palette );
-
- savequit:
- PI_FREE( palette );
- MAG_freeBuffers();
-
- return ret;
- }
-
-
- /**********************************************************************/
- /** プラグイン呼び出し関数 **/
-
- int APL_exec()
- {
- FILE *fp;
- int ret;
- FRAME fr;
-
- if( pi_imge->pix >8 ) return NOERR;
-
- fr.lupx = fr.lupy = 0;
- fr.rdwx = pi_imge->size.x-1;
- fr.rdwy = pi_imge->size.y-1;
-
-
- // if( my_getenv("USER")==NULL )
- MAG_setComment();
-
- /**/
- if( (fp=fopen( PI_FNAME,"wb" ))==NULL )
- return PI_ERROR_FILE_OPEN;
-
- ret=MAG_save( fp, pi_imge->image , &fr,
- pi_imge->pix,
- pi_imge->clut );
-
- fclose( fp );
-
- if( ret ) remove( PI_FNAME );
- /**/
-
- if( user != '\0' ) PI_FREE( user );
- if( comment != '\0' ) PI_FREE( comment );
- return ret;
- }
-
-
-
- /*************************************************************/
- /* 乙女座から得たコメントを分解する */
-
- #define iskanji(c) ( (0x81<=(c) && (c)<=0x9f) || (0xe0<=(c) && (c)<=0xfc))
- #define iskanji2(c) ( (0x40<=(c) && (c)<=0x7e) || (0x80<=(c) && (c)<=0xfc))
-
- int MAG_setComment()
- {
- int i,j,len;
-
- if( PI_COMMENT==NULL || (len=strlen( PI_COMMENT ))<1 )
- return NOERR;
-
- /* 面倒なのでメモリチェックは無視。これくらいで失敗するかな?? */
-
- for( i=0,j=0; i < LEN_USER ; i++ )
- { if( PI_COMMENT[i]==',' )
- { user=PI_MALLOC( i+1 );
- strncpy( user, PI_COMMENT, i ),user[i]='\0';
-
- for( i++;i<len; i++ )
- if( PI_COMMENT[i]!=' ' && PI_COMMENT[i]!='\t' ) break;
- if( i<len )
- { comment=PI_MALLOC( len-i+2 );
- strcpy( comment, PI_COMMENT+i );
- }
- return NOERR;
- }
- }
- user=PI_MALLOC( LEN_USER+1 );
- if( len> LEN_USER )
- comment=PI_MALLOC( len - LEN_USER +1);
- else
- { strcpy( user, PI_COMMENT );
- return NOERR;
- }
- j=0;
- /* 区切りに漢字コードが重なっている場合 念のため処理しておく */
- if( iskanji( PI_COMMENT[ LEN_USER-1 ] )
- && iskanji2( PI_COMMENT[ LEN_USER ] ) )
- j = 1;
- strncpy( user, PI_COMMENT, LEN_USER-j );user[LEN_USER-j]='\0';
- strcpy ( comment, PI_COMMENT+ LEN_USER-j );
-
- }
-
- /**********************************************************************
- ** 環境変数を取得する
- **
- ** プラグイン内部からは getenv 関数によって環境変数が獲得できないので
- ** TOS_getPath 関数により獲得する。
- ** ただしこの関数は High-C のマニュアルでは全く触れられていない!
- **
- ** int TOS_getPath( char *buf, const char *name, int len )
- ** buf 格納用バッファ(十分な大きさが必要)
- ** name 得たい環境変数名(末尾に '=' も追加しておくこと)
- ** len name の文字長
- ** 返り値
- ** 実際に得た文字長。存在しなかったとき 0 となる。
- ** ただしこの関数はパスを得るものであるため、末尾が'\\'でない場合には
- ** 勝手に'\\'が追加される。(漢字コードの区別は行われていない)
- ** また、環境変数名と'='は区別されないので、name に'='を追加しておか
- ** ないと'='も変数の内容として返される。
- */
-
- #define ENV_MAX 80
-
- char *my_getenv( name )
- char *name;
- {
- char envbuf[ ENV_MAX+1 ];
- int i;
-
- /* '='で始まって末尾に '\\' を追加したものが返される */
- if( (i=TOS_getPath( envbuf, name, strlen(name) ))==0 )
- return NULL;
-
- if( i>2 )
- { if( !iskanji( envbuf[i-2] ) ) /* 漢字コード2バイト目でない */
- envbuf[i-1] = '\0';
- }
- else if( i>0 )
- envbuf[i-1] = '\0';
-
- if( i<1 || (user = PI_MALLOC( strlen( &envbuf[1] )+1 ))==NULL )
- return '\0';
-
- strcpy( user, &envbuf[1] ); /* '=' のぶんスキップ */
-
- return user;
- }
-
-